#ifndef FORMS_HPP
#define FORMS_HPP

#include "fixit_proc.hpp"

#include <vector>
#include <string>
#include <algorithm>
#include <assert.h>

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Table.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Round_Button.H>
#include <FL/Fl_Tile.H>
#include <FL/Fl_Group.H>

namespace fix
{

	const int COLS = 2;

	class PopUpSelect : public Fl_Scroll 
	{
	private:
		std::vector<void*> w;
		std::vector<std::pair<std::string, std::string> > ss;
		
	public:
		std::pair<std::string, std::string> GetSelected()
		{
			size_t i = 0;
			for(std::vector<void*>::const_iterator it = w.begin(); it != w.end(); it++, i++)
			{
				Fl_Round_Button* in = static_cast<Fl_Round_Button*>(*it);
				assert(in != NULL);
				if ( static_cast<int>( in->value() ) )
				{
					return std::make_pair(ss.at(i).first, ss.at(i).second);
				}
			}
			return std::make_pair("", "");
		}

		PopUpSelect(const std::vector<std::pair<std::string, std::string> > Datas, int X, int Y, int W, int H, const char* L = 0) 
			: Fl_Scroll(X, Y, W, H, L),
			  ss(Datas)
		{
			int cellw = W;
			int cellh = 30;
			int xx = X, yy = Y;

			Fl_Group* group = new Fl_Group(X, Y, W, cellh*ss.size());
			for(std::vector<std::pair<std::string, std::string> >::const_iterator it = ss.begin(); it != ss.end(); it++)
			{				
				Fl_Round_Button* in = new Fl_Round_Button(xx, yy, cellw, cellh, it->first.c_str());
				in->box(FL_BORDER_BOX);
				w.push_back((void*)in);
				in->type(102);
				in->down_box(FL_ROUND_DOWN_BOX);
				xx = X;
				yy += cellh;
			}
			group->end();
			end();
		}

	};

	class GridSeries : public Fl_Table 
	{

		std::vector<SortSeries_t> vDatas;

		// Draw the row/col headings
		//    Make this a dark thin upbox with the text inside.
		//
		void DrawHeader(const char *s, int X, int Y, int W, int H) {
			fl_push_clip(X,Y,W,H);
			fl_draw_box(FL_THIN_UP_BOX, X,Y,W,H, row_header_color());
			fl_color(FL_BLACK);
			fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER);
			fl_pop_clip();
		} 
		// Draw the cell data
		//    Dark gray text on white background with subtle border
		//
		void DrawData(const char *s, int X, int Y, int W, int H) {
			fl_push_clip(X,Y,W,H);
			// Draw cell bg
			fl_color(FL_WHITE); fl_rectf(X,Y,W,H);
			// Draw cell data
			fl_color(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_BOTTOM_LEFT);
			// Draw box border
			fl_color(color()); fl_rect(X,Y,W,H);
			fl_pop_clip();
		} 
		// Handle drawing table's cells
		//     Fl_Table calls this function to draw each visible cell in the table.
		//     It's up to us to use FLTK's drawing functions to draw the cells the way we want.
		//
		void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) {
			static char s[40];
			switch ( context ) {
			case CONTEXT_STARTPAGE:                   // before page is drawn..
				fl_font(FL_HELVETICA, 16);              // set the font for our drawing operations
				return; 
			case CONTEXT_COL_HEADER:                  // Draw column headers
				if (COL == 1)
					DrawHeader("Titulo Serie Original", X, Y, W, H);
				else
					DrawHeader("Titulo Serie Procesado", X, Y, W, H);
				return; 
			case CONTEXT_ROW_HEADER:                  // Draw row headers
				sprintf(s,"%03d",ROW);                 // "001:", "002:", etc
				DrawHeader(s,X,Y,W,H);
				return; 
			case CONTEXT_CELL:                        // Draw data in cells
				if (COL == 0)
					DrawData(vDatas[ROW].TitleORG.c_str(), X, Y, W, H);			
				else
					DrawData(vDatas[ROW].TitleNEW.c_str(), X, Y, W, H);			        
				return;
			default:
				return;
			}
		}
	public:
		// Constructor
		//     Make our data array, and initialize the table options.
		//
		GridSeries(const std::vector<SortSeries_t>& datas, int X, int Y, int W, int H, const char *L=0) 
			: Fl_Table(X,Y,W,H,L) 
		{
			// Fill data array			
			vDatas = datas;
			// Rows
			rows(vDatas.size());             // how many rows
			row_header(1);              // enable row headers (along left)
			row_height_all(20);         // default height of rows
			row_resize(0);              // disable row resizing
			// Cols
			cols(COLS);					// how many columns
			col_header(1);              // enable column headers (along top)
			col_width_all(500);          // default width of columns
			col_resize(1);              // enable column resizing
			end();			// end the Fl_Table group
		}
		~GridSeries() { }

		std::vector<SortSeries_t>& GetvDatas(void) { return vDatas; }

		void Value(const std::vector<SortSeries_t>& datas)
		{
			vDatas.clear();
			vDatas = datas;
			// Rows
			rows(vDatas.size());             // how many rows
			row_header(1);              // enable row headers (along left)
			row_height_all(20);         // default height of rows
			row_resize(0);              // disable row resizing
			// Cols
			cols(COLS);					// how many columns
			col_header(1);              // enable column headers (along top)
			col_width_all(500);          // default width of columns
			col_resize(1);              // enable column resizing
			end();			// end the Fl_Table group
		}

	};


	class Forms
	{
	private:
		Fl_Input* ip_Fichero_carg;
		Fl_Input* ip_Nombre_Serie;
		Fl_Input* ip_Exp_Regular;
		Fl_Input* ip_Idioma;
		GridSeries* Grid;
		Fl_Double_Window* popUp;
		PopUpSelect* popUpTable;
		std::pair<std::string, std::string> TvSelected;

	private:
		static void help_Fichero_carga (Fl_Widget*, void*);
		static void help_Nombre_Serie (Fl_Widget*, void*);
		static void proc_radios (Fl_Widget*, void*);
		static void proc_series (Fl_Widget*, void*);
		static void proc_renombrar_series (Fl_Widget*, void*);

	public:
		Forms(void);
		~Forms(void);
		int RunForms(int argc, char* argv[]);
		const char* const patron;
		GridSeries* getGrid(void) { return Grid; }

	};

}

#endif // FORMS_HPP



